package zhieasy.cn.xpu_helper.security.detailservice;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import zhieasy.cn.model.common.Permission;
import zhieasy.cn.model.common.Role;
import zhieasy.cn.model.common.WechatUser;
import zhieasy.cn.service.common.PermissionService;
import zhieasy.cn.service.common.RoleService;
import zhieasy.cn.service.common.WechatUserService;
import zhieasy.cn.xpu_helper.security.exception.NewWechatUserException;
import zhieasy.cn.xpu_helper.security.exception.SaveNewWechatUserException;
import zhieasy.cn.xpu_helper.security.exception.SaveNewWechatUserRoleException;
import zhieasy.cn.xpu_helper.security.exception.WechatCodeException;
import zhieasy.cn.xpu_helper.security.utils.JwtUtils;

import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component("customerUserDetailsService")
public class WechatDetailsService implements UserDetailsService {
    @Autowired
    private WechatUserService wechatUserService;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private HttpSession session;

    @Autowired
    private JwtUtils jwtUtils;

    private final WxMaService wxMaService;

    public WechatDetailsService(WxMaService wxMaService) {
        this.wxMaService = wxMaService;
    }

    @Override
    public UserDetails loadUserByUsername(String wechatCode) throws UsernameNotFoundException {
        //通过code去拿到openId
        WxMaUserService userService = wxMaService.getUserService();
//        String openId = "1595991831056212889";
//        String openId = "1595991831056212888";
//        String sessionKey = "1";
        String unionId = "";
        String openId = "";
        String sessionKey = "";
        try {
            WxMaJscode2SessionResult sessionInfo = userService.getSessionInfo(wechatCode);
            unionId = sessionInfo.getUnionid();
            openId = sessionInfo.getOpenid();
            sessionKey = sessionInfo.getSessionKey();
            log.info("【WeChatController】unionId={}, openId={}, sessionKey={}", unionId, openId, sessionKey);
            //在这里我拿到了用户的信息，我需要去数据库看看他是不是第一次来
            //TODO do something.
        } catch (WxErrorException e) {
            e.printStackTrace();
            //TODO 把错误解决了，不能之抛出来
            throw  new WechatCodeException("code为空");
        }
        //1.根据用户username查询数据库是否有用户
        WechatUser wechatUser = wechatUserService.getWechatUserByOpenID(openId);

        //2.用户如果第一次登陆的话
        if(null == wechatUser){
            log.info("该用户第一次用!");
            //这个用户没有进来过,先new一个类放进去，然后等后面再发一次请求，把这个人的信息存起来
            wechatUser = new WechatUser();
            wechatUser.setWxOpenId(openId);
            wechatUser.setSessionKey(sessionKey);
            //把这个用户信息丢到session里面去
            session.setAttribute("wechatUser",wechatUser);
            //存到数据库
            boolean isSuccessInsertNewWechatUser = wechatUserService.insertWechatUser(wechatUser);
            if (!isSuccessInsertNewWechatUser){
                throw new SaveNewWechatUserException( "新用户openId为" + wechatUser.getWxOpenId() +"第一次登陆存储数据失败!");
            }
            boolean isSuccessInsertRole = roleService.assignRole(wechatUser.getWxOpenId(), 8L);
            if (!isSuccessInsertRole){
                throw new SaveNewWechatUserRoleException( "新用户openId为" + wechatUser.getWxOpenId() +"配置游客权限失败!");
            }
            //抛出这个错误,交给failHandle去处理
            throw new NewWechatUserException();
        }
        wechatUser.setSessionKey(sessionKey);
        //3.查询用户的权限
        List<Permission> permissions = permissionService.selectPermissionByOpenId(wechatUser.getWxOpenId());
        //4.获取code字段
        List<String> collect = permissions.stream().filter(item -> item !=
            null).map(item -> item.getCode()).collect(Collectors.toList());
        //5.转成数组
        String[] codes = collect.toArray(new String[collect.size()]);
        //6.把codes转成List<GrantedAuthority>
        List<GrantedAuthority> authorityList =
            AuthorityUtils.createAuthorityList(codes);
        //去数据库查一下这个人的角色
        List<Role> roleList = roleService.getWechatUserRoleListByOpenId(wechatUser.getWxOpenId());
        //把角色放到权限中去
        for (Role role: roleList) {
            authorityList.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
        }
        //authorityList.add(new SimpleGrantedAuthority("ROLE_"+))
        //7.设置权限
        wechatUser.setAuthorities(authorityList);
        //8.设置用户所有菜单
        wechatUser.setPermissionList(permissions);
        return wechatUser;
    }


    public WechatUser loadUserByOpenId(String openId) throws UsernameNotFoundException {
        WechatUser wechatUser = wechatUserService.getWechatUserByOpenID(openId);
        if(wechatUser == null){
            return null;
        }
        log.info("openId={}", openId);
        List<Permission> permissions = permissionService.selectPermissionByOpenId(wechatUser.getWxOpenId());
        //4.获取code字段
        List<String> collect = permissions.stream().filter(item -> item !=
            null).map(item -> item.getCode()).collect(Collectors.toList());
        //5.转成数组
        String[] codes = collect.toArray(new String[collect.size()]);
        //6.把codes转成List<GrantedAuthority>
        List<GrantedAuthority> authorityList =
            AuthorityUtils.createAuthorityList(codes);
        //去数据库查一下这个人的角色
        List<Role> roleList = roleService.getWechatUserRoleListByOpenId(openId);
        if (roleList.get(0) != null){
            //把角色放到权限中去
            for (Role role: roleList) {
                authorityList.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
            }
        }
        //7.设置权限
        wechatUser.setAuthorities(authorityList);
        //8.设置用户所有菜单
        wechatUser.setPermissionList(permissions);
        return wechatUser;
    }
}
